use super::task::{self, AbortHandle, AwaitHandle};
use super::{Attr, FnOnceFuture, TaskRef};
use crate::Result;
use core::future::Future;
use core::pin::Pin;
use core::task::{Context, Poll};

/// 注意返回值类型为`Result<Future::Output>`.
/// 业务层负责处理异步调度失败的返回值.
/// 应该只在同步环境中使用，调用JoinHandle::join获取返回值. 对应runtime::spawn系列函数的返回值
pub struct JoinHandle<T>(AwaitHandle<T>);

impl<T> JoinHandle<T> {
    /// 获取返回值，注意返回值类型为Result<T>, 可能因为运行时资源受限而无法创建Task.
    pub fn join(self) -> <AwaitHandle<T> as Future>::Output {
        self.0.join()
    }

    /// 取消任务，如果成功取消则返回TRUE，否则说明异步任务已经执行完毕，取消失败.
    pub fn abort(&self) -> bool {
        self.0.abort()
    }

    /// 任务是否已经结束，可能是正常结束，也可能是被abort中断, 只要不再需要调度，则返回true.
    pub fn is_finished(&self) -> bool {
        self.0.is_finished()
    }

    /// 返回的AbortHandl不支持join操作，只是代表不再关心返回值.
    pub fn abort_handle(self) -> AbortHandle<T> {
        self.0.abort_handle()
    }
}

impl<T> JoinHandle<T> {
    pub(crate) fn new(task: TaskRef) -> Self {
        Self(AwaitHandle::new(task))
    }

    pub(crate) fn null() -> Self {
        Self(AwaitHandle::null())
    }

    pub(crate) fn handle(self) -> AwaitHandle<T> {
        self.0
    }
}

impl<T> Future for JoinHandle<T> {
    type Output = Result<T>;
    fn poll(mut self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output> {
        let pinned = unsafe { Pin::new_unchecked(&mut self.0) };
        Future::poll(pinned, ctx)
    }
}

/// 提供批量任务的创建工作，可以更高效的等待全部任务或者任何一个子任务的结束.
/// 可以在同步环境下创建异步子任务，但只能在异步环境下等待子任务的结束.
#[repr(C)]
pub struct JoinSet<T>(task::JoinSet<T>);

impl<T> Default for JoinSet<T> {
    fn default() -> Self {
        Self(task::JoinSet::default())
    }
}

impl<T> JoinSet<T> {
    /// 创建JoinSet，用于在一个异步环境下等待多个异步子任务执行完毕.
    /// 异步子任务可以在同步环境下创建.
    pub const fn new() -> Self {
        Self(task::JoinSet::new())
    }

    /// 是否创建了异步子任务.
    pub fn is_empty(&self) -> bool {
        self.0.is_empty()
    }

    /// 异步子任务的数量.
    pub fn len(&self) -> usize {
        self.0.len()
    }

    /// 创建异步子任务.
    pub fn spawn<F>(&mut self, future: F) -> Result<()>
    where
        F: Future<Output = T> + Send + 'static,
        T: Send + 'static,
    {
        self.spawn_with(future, &Attr::default())
    }

    /// 创建异步子任务.
    pub fn spawn_with<F>(&mut self, future: F, attr: &Attr) -> Result<()>
    where
        F: Future<Output = T> + Send + 'static,
        T: Send + 'static,
    {
        let attr = task::JoinSet::<T>::join_attr(attr);
        let handle = super::spawn_with(future, &attr);
        self.0.push_handle(handle.handle())
    }

    /// 创建异步子任务, 只能在本线程被调度.
    pub fn spawn_local<F>(&mut self, future: F) -> Result<()>
    where
        F: Future<Output = T> + 'static,
        T: 'static,
    {
        self.spawn_local_with(future, &Attr::default())
    }

    /// 创建异步子任务, 只能在本线程被调度.
    pub fn spawn_local_with<F>(&mut self, future: F, attr: &Attr) -> Result<()>
    where
        F: Future<Output = T> + 'static,
        T: 'static,
    {
        let attr = task::JoinSet::<T>::join_attr(attr);
        let handle = super::spawn_local_with(future, &attr);
        self.0.push_handle(handle.handle())
    }

    /// 创建异步子任务.
    pub fn spawn_fn<F>(&mut self, f: F) -> Result<()>
    where
        F: FnOnce() -> T + Send + 'static,
        T: Send + 'static,
    {
        self.spawn(FnOnceFuture::new(f))
    }

    /// 创建异步子任务.
    pub fn spawn_fn_with<F>(&mut self, f: F, attr: &Attr) -> Result<()>
    where
        F: FnOnce() -> T + Send + 'static,
        T: Send + 'static,
    {
        self.spawn_with(FnOnceFuture::new(f), attr)
    }

    /// 创建异步子任务.
    pub fn spawn_fn_local<F>(&mut self, f: F) -> Result<()>
    where
        F: FnOnce() -> T + 'static,
        T: 'static,
    {
        self.spawn_local(FnOnceFuture::new(f))
    }

    /// 创建异步子任务.
    pub fn spawn_fn_local_with<F>(&mut self, f: F, attr: &Attr) -> Result<()>
    where
        F: FnOnce() -> T + Send + 'static,
        T: Send + 'static,
    {
        self.spawn_local_with(FnOnceFuture::new(f), attr)
    }

    /// 取消所有异步子任务.
    pub fn abort(&mut self) {
        self.0.abort();
    }

    /// 等待所有任务结束后返回每个任务的执行结果.
    /// 执行结果的数据类型为`(id, Result<T>)`, `id`为`JoinSet::spawn`, 即任务创建的顺序，从0开始.
    /// 相对顺序等待每个任务的结束，比如:
    /// `
    /// for h in handles {
    ///     h.await;
    /// }
    /// `
    /// 本方法更加高效，只有全部子任务都结束后才会唤醒本任务.
    pub async fn wait_all(&mut self) -> impl Iterator<Item = (usize, Result<T>)> + '_ {
        self.0.wait_all().await
    }

    /// 等待任何一个任务结束后即返回任务的执行结果.
    /// 执行结果的数据类型为`(id, Result<T>)`, `id`为`JoinSet::spawn`, 即任务创建的顺序，从0开始.
    /// 相对顺序等待每个任务的结束，比如:
    /// `
    /// for h in handles {
    ///     h.await;
    /// }
    /// `
    /// 本方法更加高效，其返回顺序取决于任务结束顺序而非任务的创建顺序
    pub async fn wait_any(&mut self) -> Option<(usize, Result<T>)> {
        self.0.wait_any().await
    }
}
